package com.softserveinc.moviedbapp.manager;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.softserveinc.moviedbapp.util.MovieAppConstants;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

public class BitMapManager {

	private int retrys = MovieAppConstants.RETRY_COUNT;
	private static String TAG = BitMapManager.class.getSimpleName();
	private File mCacheDir;
	private Bitmap currentBitmap;

	/* get a bitmap for an image from the local storage */
	public synchronized Bitmap fetchBitmap(final String url) {
		Log.d(TAG, "fetchBitmap() " + url);
		if (url == null) {
			return null;
		}
		String filename = "img" + String.valueOf(url.hashCode()) + ".png";
		File file = new File(mCacheDir, filename);

		if (!isBitmapCached(file)) {
			/* Nope, have to download it */
			currentBitmap = loadBitmapFromWeb(url);
			/* save bitmap to cache for later */
			storePoster(currentBitmap, file);
		}
		return currentBitmap;
	}

	private boolean isBitmapCached(final File file) {
		/* Is the bitmap in our cache? */
		currentBitmap = BitmapFactory.decodeFile(file.getPath());
		if (currentBitmap != null) {
			return true;
		}
		return false;
	}

	/* get a bitmap for an image from the network */
	private Bitmap loadBitmapFromWeb(final String url) {

		Bitmap bitmap = null;
		URL thumbPosterUrl;
		try {
			thumbPosterUrl = new URL(url);
		} catch (MalformedURLException e) {
			Log.e(TAG, "MalformedURLException " + url, e);
			return null;
		}

		/* try for 5 times to load image */
		InputStream is = null;
		while (retrys > 0) {
			Log.d(TAG, "url is correct. Going to decodeStream");
			try {
				is = thumbPosterUrl.openStream();
				bitmap = BitmapFactory.decodeStream(is);
			} catch (IOException e) {
				retrys--;
				Log.e(TAG, "failed to load a bitmap after " + retrys + " attemps", e);
				continue;
			} finally {
				if (is != null) {
					try {
						Log.d(TAG, "closing input stream");
						is.close();
					} catch (IOException e) {
						Log.e(TAG, "unable to close input stream", e);
					}
				}
			}
			/* BitmapFactory.decodeStream can return null so try again */
			if (bitmap == null) {
				retrys--;
				Log.e(TAG, "bitmap is null " + retrys + " re trys left");
				continue;
			}
			Log.d(TAG, "loaded a bitmap for " + url + " form web");
			break;
		}
		retrys = MovieAppConstants.RETRY_COUNT;
		return bitmap;
	}

	/* store the image on sd card or in cache dir */
	private void storePoster(final Bitmap bitmap, final File file) {

		FileOutputStream out = null;
		if (bitmap != null) {
			try {
				out = new FileOutputStream(file);
				bitmap.compress(Bitmap.CompressFormat.PNG, 80, out);
				Log.d(TAG, "POSTER WAS STORED " + file.getPath());
			} catch (Exception e) {
				e.printStackTrace();
				Log.e(TAG, "couldn't store the file", e);
			} finally {
				try {
					if (out != null) {
						out.close();
						Log.e(TAG, "closing the output stream");
					}
				} catch (Exception ex) {
					Log.e(TAG, "couldn't close the output stream", ex);
				}
			}
		} else {
			Log.d(TAG, "Poster WAS NOT STORED");
		}
	}

	public File getCacheDir() {
		return mCacheDir;
	}

	public void setCacheDir(final File mCacheDir) {
		this.mCacheDir = mCacheDir;
	}

}
